package cn.fenqing168.bio;

import lombok.SneakyThrows;
import lombok.val;

import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;

/**
 * bio 服务端
 * @author fenqing
 */
public class BioServer {

    static List<OutputStream> sockets = new ArrayList<>();

    @SneakyThrows
    public static void main(String[] args) {

        //1.创建线程池
        val executorService = Executors.newCachedThreadPool();
        //2.创建服务端socket
        ServerSocket serverSocket = new ServerSocket(8888);
        printThread("服务器已启动，端口：8888");
        //3.循环等待连接
        while (true){
            printThread("等待连接");
            final val accept = serverSocket.accept();
            printThread("连接成功");
            executorService.execute(() -> handler(accept));
        }
        //4.获取到一个连接，开启一个线程执行

    }

    public static void printThread(String text){
        final val thread = Thread.currentThread();
        System.out.printf("当前线程[id:%d,name:%s],%s\n", thread.getId(), thread.getName(), text);
    }

    /**
     * 处理请求
     * @param socket 连接
     */
    public static void handler(Socket socket){

        try(final val inputStream = socket.getInputStream();
            final val outputStream = socket.getOutputStream()){
            sockets.add(outputStream);
            final val bytes = new byte[1024];
            int len;
            while ((len = inputStream.read(bytes)) != -1){
                printThread("读取到数据");
                final val s = new String(bytes, 0, len, StandardCharsets.UTF_8);
                printThread(s);
                send(outputStream, s);

            }
        }catch (Exception e){
            printThread("出现异常");
            e.printStackTrace();
        }finally {
            sockets.remove(socket);
        }
    }

    public static void send(OutputStream thisOutputStream, String text){
        sockets.stream().filter(item -> item != thisOutputStream).forEach(item -> {
            try {
                final val thread = Thread.currentThread();
                item.write((String.format("线程[id:%d,name:%s]说：", thread.getId(), thread.getName()) + text).getBytes(StandardCharsets.UTF_8));
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }

}
